package com.thiswhyme.sentinel.server2.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.thiswhyme.common.expection.BusinessException;
import com.thiswhyme.common.response.ResponseVo;
import com.thiswhyme.sentinel.server2.controller.dto.UserDto;
import com.thiswhyme.sentinel.server2.handler.BizBlockHandler;
import com.thiswhyme.sentinel.server2.handler.BizFallbackHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.List;

/**
 * 注解+配置方式demo
 * Created by thiswhyme on 2020/8/16.
 */
@RestController
@RequestMapping("/config-demo/")
public class ConfigDemoController {

    /**
     * 限流-无fallback&blockHandler
     * @return
     */
    @SentinelResource(value = "user-list")
    @GetMapping("user-list")
    public ResponseVo<List<UserDto>> listUsers() {
        List<UserDto> data = Arrays.asList(new UserDto().setUserId(666).setName("sentinel-test"),
                new UserDto().setUserId(888).setName("sentinel-test2"));
        return ResponseVo.success(data);
    }

    /**
     * 限流-有blockHandler
     * @param userId
     * @return
     */
    @SentinelResource(value = "user-name", //资源名
            blockHandlerClass = BizBlockHandler.class, //限流异常处理方法所在类（若不指定则默认在本类中找）
            blockHandler = "queryUserNameBlockHandle" //限流异常处理方法
    )
    @GetMapping("user-name")
    public ResponseVo<Integer> queryUserName(@RequestParam Integer userId) {
        return ResponseVo.success(userId);
    }

    /**
     * 限流-有defaultFallback
     * @param userId
     * @return
     */
    @SentinelResource(value = "user-name", //资源名
            fallbackClass = BizFallbackHandler.class, //fallback方法所在类（若不指定则默认在本类中找）
            defaultFallback = "defaultFallbackHandle", //默认fallback方法
            exceptionsToIgnore = {IllegalArgumentException.class})//需要忽略的异常，方法抛出该异常时会直接抛出，sentinel不处理
    @GetMapping("user-name1")
    public ResponseVo<Integer> queryUserName1(@RequestParam Integer userId) {
        if(0 == userId) {
            throw new IllegalArgumentException("userId应当大于0");
        } else if(1 == userId) {
            throw new BusinessException("userId为1的用户不存在");
        }
        return ResponseVo.success(userId);
    }

    /**
     * 热点参数限流-有fallback
     * @param userId
     * @return
     * @throws InterruptedException
     */
    @SentinelResource(value = "user-name2", //资源名
            fallbackClass = BizFallbackHandler.class, //fallback方法所在类（若不指定则默认在本类中找）
            fallback = "queryUserName2FallbackHandle", //fallback方法
            exceptionsToIgnore = {IllegalArgumentException.class} //需要忽略的异常，方法抛出该异常时会直接抛出，sentinel不处理
            )
    @GetMapping("user-name2")
    public ResponseVo<Integer> queryUserName2(@RequestParam Integer userId) {
        return ResponseVo.success(userId);
    }

    /**
     * 限流-有defaultFallback&blockHandler
     * @param userId
     * @return
     */
    @SentinelResource(value = "user-name", //资源名
            blockHandlerClass = BizBlockHandler.class, //限流异常处理方法所在类（若不指定则默认在本类中找）
            blockHandler = "queryUserNameBlockHandle", //限流异常处理方法
            fallbackClass = BizFallbackHandler.class, //fallback方法所在类（若不指定则默认在本类中找）
            defaultFallback = "defaultFallbackHandle", //默认fallback方法
            exceptionsToIgnore = {IllegalArgumentException.class})//需要忽略的异常，方法抛出该异常时会直接抛出，sentinel不处理
    @GetMapping("user-name3")
    public ResponseVo<String> queryUserName3(@RequestParam Integer userId) {
        throw new BusinessException(String.format("userId为%s的用户不存在", userId));
    }
}
